﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using System.Collections;
using Microsoft.Office.Server.Search.Administration;
using Microsoft.Office.Server;
using System.Web.UI;
using SearchAdminToolkit.Libary;

namespace SearchAdminToolkit.UI.Controls
{
    /// <summary>
    /// Defines a control for managing SharePoint Managed Properties.
    /// </summary>
    public class ManagedPropertyToolkitControl : BaseToolkitControl, INamingContainer
    {

        #region Fields

        private GridView _propertyGrid;
        private TextBox _keywordInput;
        private Button _searchButton;

        #endregion

        #region Properties

        /// <summary>
        /// Gets the contained search button.
        /// </summary>
        private Button SearchButton
        {
            get
            {
                if (_searchButton == null)
                {
                    _searchButton = new Button();
                    _searchButton.CssClass = "ms-ButtonHeightWidth2";
                    _searchButton.Text = "Search";
                }
                return _searchButton;
            }
        }

        /// <summary>
        /// Gets the contained keyword textbox.
        /// </summary>
        private TextBox KeywordInput
        {
            get
            {
                if (_keywordInput == null)
                {
                    _keywordInput = new TextBox();
                    _keywordInput.CssClass = "ms-long";
                }
                return _keywordInput;
            }
        }

        /// <summary>
        /// Gets the contained grid view of managed properties.
        /// </summary>
        private GridView PropertyGrid
        {
            get
            {
                if (_propertyGrid == null)
                {
                    _propertyGrid = new GridView();
                }

                return _propertyGrid;
            }
        }

        /// <summary>
        /// Gets the current sort order for the grid view.
        /// </summary>
        private SortDirection SortDirection
        {
            get
            {
                if (ViewState["_propertyGridSortDirection"] != null)
                {
                    return (SortDirection)ViewState["_propertyGridSortDirection"];
                }

                return SortDirection.Ascending;
            }
            set
            {
                ViewState["_propertyGridSortDirection"] = value;
            }
        }

        #endregion

        #region Methods
        
        /// <summary>
        /// Gets the section title.
        /// </summary>
        /// <returns></returns>
        protected override string GetSectionTitle()
        {
            return "Managed Property Relevance Settings";
        }

        /// <summary>
        /// Gets the section description.
        /// </summary>
        /// <returns></returns>
        protected override string GetSectionDescription()
        {
            return "Use the table below to manage the weights and length normalization values of managed properties to adjust relevance.<br /><br />";
        }

        /// <summary>
        /// Overridden to create this composite control.
        /// </summary>
        protected override void CreateChildControls()
        {

            this.Controls.Add(this.KeywordInput);

            this.SearchButton.Click += new EventHandler(SearchButton_Click);
            this.Controls.Add(this.SearchButton);

            this.InitializePropertyGrid();

            this.PropertyGrid.RowEditing += new GridViewEditEventHandler(PropertyGrid_RowEditing);
            this.PropertyGrid.RowUpdating += new GridViewUpdateEventHandler(PropertyGrid_RowUpdating);
            this.PropertyGrid.Sorting += new GridViewSortEventHandler(PropertyGrid_Sorting);
            this.PropertyGrid.RowCancelingEdit += new GridViewCancelEditEventHandler(PropertyGrid_RowCancelingEdit);
            this.PropertyGrid.PageIndexChanging += new GridViewPageEventHandler(PropertyGrid_PageIndexChanging);
            this.PropertyGrid.Load += new EventHandler(PropertyGrid_Load);

            this.Controls.Add(this.PropertyGrid);

            base.CreateChildControls();
        }

        /// <summary>
        /// Overridden to render the composite control.
        /// </summary>
        /// <param name="writer"></param>
        protected override void RenderToolkitControl(System.Web.UI.HtmlTextWriter writer)
        {

            // <label>
            writer.RenderBeginTag(HtmlTextWriterTag.Label);
            writer.Write("Keyword:");
            // </label>
            writer.RenderEndTag();

            writer.Write("&nbsp;");

            // <input type="text" />
            this.KeywordInput.RenderControl(writer);
            writer.Write("&nbsp;");

            // <input type="button" />
            this.SearchButton.RenderControl(writer);
            writer.RenderBeginTag(HtmlTextWriterTag.Br);
            writer.RenderEndTag();

            // grid
            this.PropertyGrid.RenderControl(writer);

        }

        /// <summary>
        /// Initializes the contained property grid.
        /// </summary>
        private void InitializePropertyGrid()
        {
            this.PropertyGrid.AllowPaging = true;
            this.PropertyGrid.AllowSorting = true;

            GridViewUtility.ApplyStyles(this.PropertyGrid);

            this.PropertyGrid.DataKeyNames = new string[] { "ID" };
            this.PropertyGrid.Columns.Add(GridViewUtility.CreateEditCommandField());
            this.PropertyGrid.Columns.Add(GridViewUtility.CreateBoundField("Property", "Name", true));
            this.PropertyGrid.Columns.Add(GridViewUtility.CreateBoundField("Weight", "Weight", false));
            this.PropertyGrid.Columns.Add(GridViewUtility.CreateBoundField("Length Normalization", "LengthNormalization", false));

        }

        /// <summary>
        /// Binds the managed properties to the contained grid.
        /// </summary>
        private void BindPropertyGrid(string keyword)
        {
            try
            {
                this.PropertyGrid.DataSource = PropertyManager.FindByName(keyword);
                this.PropertyGrid.DataBind();
            }
            catch (Exception e)
            {
                Page.Response.Write(e.Message);
            }
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Responds to the event raised when a column header is clicked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void PropertyGrid_Sorting(object sender, GridViewSortEventArgs e)
        {                
            this.PropertyGrid.EditIndex = -1;

            IQueryable<ManagedProperty> items = PropertyManager.FindByName(this.KeywordInput.Text).AsQueryable<ManagedProperty>();

            if (this.SortDirection == SortDirection.Ascending)
            {
                this.SortDirection = SortDirection.Descending;
                this.PropertyGrid.DataSource = items.OrderBy(e.SortExpression).ToList<ManagedProperty>();
            }
            else
            {
                this.SortDirection = SortDirection.Ascending;
                this.PropertyGrid.DataSource = items.OrderBy(e.SortExpression).Reverse<ManagedProperty>().ToList<ManagedProperty>();
            }

            this.PropertyGrid.DataBind();

        }

        /// <summary>
        /// Responds to the event raised when a grow row is being updated.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void PropertyGrid_RowUpdating(object sender, GridViewUpdateEventArgs e)
        {
            try
            {
                GridViewUtility.SynchronizeNewValues(e, this.PropertyGrid);

                // **************** DevConnections Manage Weights and Length Normalization

                // retrieve the weight / length normalization and key of the managed property
                float weight = Convert.ToSingle(e.NewValues["Weight"]);
                float lengthNormalization = Convert.ToSingle(e.NewValues["LengthNormalization"]);

                if ((lengthNormalization < 0) || (lengthNormalization > 1))
                {
                    this.SetErrorMessage("The length normalization value must be a value between 0 and 1.");
                }
                else if ((weight < 0) || (weight > 10000))
                {
                    this.SetErrorMessage("The property weight must be a value between 0 and 10,000.");
                }
                else
                {
                    string key = this.PropertyGrid.DataKeys[e.RowIndex].Value.ToString();

                    // **************** DevConnections Manage Weights and Length Normalization
                    PropertyManager.Update(key, weight, lengthNormalization);
                    // **************** DevConnections Manage Weights and Length Normalization

                    // take the grid out of edit mode and rebind.
                    this.PropertyGrid.EditIndex = -1;
                    this.BindPropertyGrid(this.KeywordInput.Text);
                }
            }
            catch (Exception ex)
            {
                this.SetErrorMessage(string.Format("The following error occurred when attempting to update the managed property: {0}", ex.Message));
            }
        }

        /// <summary>
        /// Responds to the event raised when the grid view page index is changed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void PropertyGrid_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            this.PropertyGrid.PageIndex = e.NewPageIndex;
            this.BindPropertyGrid(this.KeywordInput.Text);
        }

        /// <summary>
        /// Responds to the event raised when the property grid is being edited.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void PropertyGrid_RowEditing(object sender, GridViewEditEventArgs e)
        {
            this.PropertyGrid.EditIndex = e.NewEditIndex;
            this.BindPropertyGrid(this.KeywordInput.Text);
        }

        /// <summary>
        /// Responds to the event raised when the property grid is leaving edit mode.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void PropertyGrid_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
        {
            this.PropertyGrid.EditIndex = -1;
            this.BindPropertyGrid(this.KeywordInput.Text);
        }

        /// <summary>
        /// Responds to the event raised when the grid is loaded.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void PropertyGrid_Load(object sender, EventArgs e)
        {
            if (this.PropertyGrid.Rows.Count == 0)
            {
                this.BindPropertyGrid(string.Empty);
            }
        }

        /// <summary>
        /// Responds to the event raised when the search button is clicked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void SearchButton_Click(object sender, EventArgs e)
        {
            this.PropertyGrid.PageIndex = 0;
            this.BindPropertyGrid(this.KeywordInput.Text);
        }

        #endregion

    }
}
